home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / ADVANCED / RASONLY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  7.8 KB  |  327 lines

  1. /*
  2.  * rasonly.c -
  3.  *      Demonstrates the use of OpenGL for rasterization-only, with
  4.  *      perspective-correct texture mapping.
  5.  *
  6.  * Michael I. Gold <gold@sgi.com>
  7.  * Silicon Graphics Computer Systems, May 1997
  8.  *
  9.  * Since current low-end 3D accelerators support only rasterization in
  10.  * hardware, a number of developers have expressed interested in using
  11.  * OpenGL as an interface to rasterization hardware while retaining
  12.  * control of transformations and lighting in the application code.
  13.  * Many OpenGL implementations detect and optimize for identity xforms,
  14.  * so this approach is entirely reasonable.
  15.  *
  16.  * Setting up rasterization-only is fairly straightforward.  The projection
  17.  * matrix is set up as a one-to-one mapping between eye and clip coordinates,
  18.  * and the modelview matrix is set up as identity, e.g. object coordinates
  19.  * map directly to eye coordinates.  This can be achieved as follows:
  20.  *
  21.  *      glMatrixMode(GL_PROJECTION);
  22.  *      glLoadIdentity();
  23.  *      glOrtho(0.0f, (GLfloat) width, 0.0f, (GLfloat) height, -1.0f, 1.0f);
  24.  *      glMatrixMode(GL_MODELVIEW);
  25.  *      glLoadIdentity();
  26.  *      glViewport(0, 0, width, height);
  27.  *
  28.  * where (width, height) represent the window dimensions.
  29.  *
  30.  * Now transformed geometry may be specified directly through the standard
  31.  * interfaces (e.g. glVertex*()).  The only tricky part that remains is
  32.  * specifying texture coordinates such that perspective correction may
  33.  * occur.  The answer is to use glTexCoord4*(), and perform the perspective
  34.  * divide on the texture coordinates directly.
  35.  */
  36.  
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <GL/glut.h>
  40.  
  41. GLboolean motion = GL_TRUE;
  42.  
  43. /* Matrices */
  44. GLfloat rot = 0.0f;
  45. GLfloat ModelView[16];
  46. GLfloat Projection[16];
  47. GLfloat Viewport[4];
  48.  
  49. /* Sample geometry */
  50. GLfloat quadV[][4] = {
  51.     { -1.0f, 0.0f, -1.0f, 1.0f },
  52.     {  1.0f, 0.0f, -1.0f, 1.0f },
  53.     {  1.0f, 0.5f, -0.2f, 1.0f },
  54.     { -1.0f, 0.5f, -0.2f, 1.0f },
  55. };
  56.  
  57. GLfloat quadC[][3] = {
  58.     { 1.0f, 0.0f, 0.0f },
  59.     { 0.0f, 1.0f, 0.0f },
  60.     { 0.0f, 0.0f, 1.0f },
  61.     { 1.0f, 1.0f, 1.0f },
  62. };
  63.  
  64. GLfloat quadT[][2] = {
  65.     { 0.0f, 0.0f },
  66.     { 0.0f, 1.0f },
  67.     { 1.0f, 1.0f },
  68.     { 1.0f, 0.0f },
  69. };
  70.  
  71. /*********************************************************************
  72.  * Utility functions
  73.  */
  74.  
  75. int texWidth = 128;
  76. int texHeight = 128;
  77.  
  78. /* Create and download the application texture map */
  79. static void
  80. setCheckedTexture(void)
  81. {
  82.     int texSize;
  83.     void *textureBuf;
  84.     GLubyte *p;
  85.     int i,j;
  86.  
  87.     /* malloc for rgba as worst case */
  88.     texSize = texWidth*texHeight*4;
  89.  
  90.     textureBuf = malloc(texSize);
  91.     if (NULL == textureBuf) return;
  92.  
  93.     p = (GLubyte *)textureBuf;
  94.     for (i=0; i < texWidth; i++) {
  95.         for (j=0; j < texHeight; j++) {
  96.             if ((i ^ j) & 8) {
  97.                 p[0] = 0xff; p[1] = 0xff; p[2] = 0xff; p[3] = 0xff;
  98.             } else {
  99.                 p[0] = 0x08; p[1] = 0x08; p[2] = 0x08; p[3] = 0xff;
  100.             }
  101.             p += 4;
  102.         }
  103.     }
  104.     gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight, 
  105.                  GL_RGBA, GL_UNSIGNED_BYTE, textureBuf);
  106.     free(textureBuf);
  107. }
  108.  
  109. /* Perform one transform operation */
  110. static void
  111. Transform(GLfloat *matrix, GLfloat *in, GLfloat *out)
  112. {
  113.     int ii;
  114.  
  115.     for (ii=0; ii<4; ii++) {
  116.         out[ii] = 
  117.             in[0] * matrix[0*4+ii] +
  118.             in[1] * matrix[1*4+ii] +
  119.             in[2] * matrix[2*4+ii] +
  120.             in[3] * matrix[3*4+ii];
  121.     }
  122. }
  123.  
  124. /* Transform a vertex from object coordinates to window coordinates.
  125.  * Lighting is left as an exercise for the reader.
  126.  */
  127. static void
  128. DoTransform(GLfloat *in, GLfloat *out)
  129. {
  130.     GLfloat tmp[4];
  131.     GLfloat invW;       /* 1/w */
  132.  
  133.     /* Modelview xform */
  134.     Transform(ModelView, in, tmp);
  135.  
  136.     /* Lighting calculation goes here! */
  137.  
  138.     /* Projection xform */
  139.     Transform(Projection, tmp, out);
  140.  
  141.     if (out[3] == 0.0f) /* do what? */
  142.         return;
  143.  
  144.     invW = 1.0f / out[3];
  145.  
  146.     /* Perspective divide */
  147.     out[0] *= invW;
  148.     out[1] *= invW;
  149.     out[2] *= invW;
  150.  
  151.     /* Map to 0..1 range */
  152.     out[0] = out[0] * 0.5f + 0.5f;
  153.     out[1] = out[1] * 0.5f + 0.5f;
  154.     out[2] = out[2] * 0.5f + 0.5f;
  155.  
  156.     /* Map to viewport */
  157.     out[0] = out[0] * Viewport[2] + Viewport[0];
  158.     out[1] = out[1] * Viewport[3] + Viewport[1];
  159.  
  160.     /* Store inverted w for performance */
  161.     out[3] = invW;
  162. }
  163.  
  164. /*********************************************************************
  165.  * Application code begins here
  166.  */
  167.  
  168. /* For the sake of brevity, I'm use OpenGL to compute my matrices. */
  169. void UpdateModelView(void)
  170. {
  171.     glPushMatrix();
  172.     glLoadIdentity();
  173.     gluLookAt(0.0f, 1.0f, -4.0f,
  174.               0.0f, 0.0f, 0.0f,
  175.               0.0f, 1.0f, 0.0f);
  176.     glRotatef(rot, 0.0f, 1.0f, 0.0f);
  177.     /* Retrieve the matrix */
  178.     glGetFloatv(GL_MODELVIEW_MATRIX, ModelView);
  179.     glPopMatrix();
  180. }
  181.  
  182. void InitMatrices(void)
  183. {
  184.     /* Calculate projection matrix */
  185.     glMatrixMode(GL_PROJECTION);
  186.     glPushMatrix();
  187.     glLoadIdentity();
  188.     gluPerspective(45.0f, 1.0f, 1.0f, 100.0f);
  189.     /* Retrieve the matrix */
  190.     glGetFloatv(GL_PROJECTION_MATRIX, Projection);
  191.     glPopMatrix();
  192.     glMatrixMode(GL_MODELVIEW);
  193.  
  194.     UpdateModelView();
  195. }
  196.  
  197. void Init(void)
  198. {
  199.     glClearColor(0.2f, 0.2f, 0.6f, 1.0f);
  200.  
  201.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  202.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  203.     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  204.     glEnable(GL_TEXTURE_2D);
  205.     glEnable(GL_DEPTH_TEST);
  206.     setCheckedTexture();
  207.  
  208.     InitMatrices();
  209. }
  210.  
  211. void Redraw(void)
  212. {
  213.     GLfloat tmp[4];
  214.     int ii;
  215.  
  216.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  217.  
  218.     glBegin(GL_QUADS);
  219.  
  220.     for (ii = 0; ii < 4; ii++) {
  221.  
  222.         /* Transform a vertex from object to window coordinates.
  223.          * 1/w is returned as tmp[3] for perspective-correcting
  224.          * the texture coordinates.
  225.          */
  226.         DoTransform(quadV[ii], tmp);
  227.  
  228.         /* Ideally the colors will be computed by the lighting equation,
  229.          * but I've hard-coded values for this example.
  230.          */
  231.         glColor3fv(quadC[ii]);
  232.  
  233.         /* Scale by 1/w (stored in tmp[3]) */
  234.         glTexCoord4f(quadT[ii][0] * tmp[3],
  235.                      quadT[ii][1] * tmp[3], 0.0f, tmp[3]);
  236.  
  237.         /* Note I am using Vertex3, not Vertex4, since we have already
  238.          * performed the perspective divide.
  239.          */
  240.         glVertex3fv(tmp);
  241.     }
  242.  
  243.     glEnd();
  244.  
  245.     glutSwapBuffers();
  246. }
  247.  
  248. void Motion(void)
  249. {
  250.     rot += 3.0f;
  251.     if (rot >= 360.0f) rot -= 360.0f;
  252.     UpdateModelView();
  253.     Redraw();
  254. }
  255.  
  256. /* ARGSUSED1 */
  257. void Key(unsigned char key, int x, int y)
  258. {
  259.     switch (key) {
  260.     case 27:
  261.         exit(0);
  262.     case 'm':
  263.         motion = !motion;
  264.         glutIdleFunc(motion ? Motion : NULL);
  265.         break;
  266.     }
  267. }
  268.  
  269. /* ARGSUSED1 */
  270. void Button(int button, int state, int x, int y)
  271. {
  272.     switch (button) {
  273.     case GLUT_LEFT_BUTTON:
  274.         if (state == GLUT_DOWN) {
  275.             rot -= 15.0f;
  276.             UpdateModelView();
  277.             Redraw();
  278.         }
  279.         break;
  280.     case GLUT_RIGHT_BUTTON:
  281.         if (state == GLUT_DOWN) {
  282.             rot += 15.0f;
  283.             UpdateModelView();
  284.             Redraw();
  285.         }
  286.         break;
  287.     }
  288. }
  289.  
  290. void Reshape(int width, int height)
  291. {
  292.     glMatrixMode(GL_PROJECTION);
  293.     glLoadIdentity();
  294.     glOrtho(0.0f, (GLfloat) width, 0.0f, (GLfloat) height, -1.0f, 1.0f);
  295.  
  296.     glMatrixMode(GL_MODELVIEW);
  297.     glLoadIdentity();
  298.  
  299.     glViewport(0, 0, width, height);
  300.  
  301.     Viewport[0] = Viewport[1] = 0.0f;
  302.     Viewport[2] = (GLfloat) width;
  303.     Viewport[3] = (GLfloat) height;
  304. }
  305.  
  306. int
  307. main(int argc, char *argv[])
  308. {
  309.     char *t;
  310.     glutInit(&argc, argv);
  311.     glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
  312.     glutInitWindowSize(400, 400);
  313.     glutCreateWindow((t=strrchr(argv[0], '\\')) != NULL ? t+1 : argv[0]);
  314.  
  315.     Init();
  316.  
  317.     glutDisplayFunc(Redraw);
  318.     glutReshapeFunc(Reshape);
  319.     glutKeyboardFunc(Key);
  320.     glutMouseFunc(Button);
  321.     glutIdleFunc(Motion);
  322.  
  323.     glutMainLoop();
  324.  
  325.     return 0;
  326. }
  327.